#include "forco_os.h"
//定义一个全局变量
OS_RDY_LIST  OSRdyList;
extern OS_TCB      IDLETaskTCB;

//初始化链表
void OS_RdyListInit(void)
{
    OSRdyList.RdylistHead       = (OS_TCB*)0;
    OSRdyList.RdyCount          = 0;
}

//插入一个任务控制块到就绪表
void OS_RdyListInsert(OS_TCB *p_tcb)
{
    OS_TCB *p_tcb1;
    OS_TCB *p_tcb2;
    //设置优先级位
    OS_PrioInsert(p_tcb->taskprio);
    //就绪表为空,直接插入
    if((OS_TCB*)0 == OSRdyList.RdylistHead){
        //任务控制块到前后都为0
        OSRdyList.RdyCount       = 1;
        p_tcb->NextPtr           = (OS_TCB*)0;
        p_tcb->PrevPtr           = (OS_TCB*)0;
        OSRdyList.RdylistHead    = p_tcb;
    }else{
        p_tcb1  =   OSRdyList.RdylistHead;
        //按照优先级从高到低排序,即优先级数字从小到大排序
        //如果当前的列表的数字为3,4,5,8
        //找插入位置
        while((OS_TCB*)0 != p_tcb1){
            if(p_tcb->taskprio < p_tcb1->taskprio)
            {
               //第一种情况，插入的值为2，在最前面
               if(p_tcb1->PrevPtr == (OS_TCB*)0){
                    p_tcb->PrevPtr              = (OS_TCB*)0;
                    p_tcb->NextPtr              = p_tcb1;
                    p_tcb1->PrevPtr             = p_tcb;
                    OSRdyList.RdylistHead       = p_tcb;
               }else{
               //第二种情况是插入在两者之间,例如插入的是6
                    //5的节点
                    p_tcb2                      = p_tcb1->PrevPtr;
                    //5节点的下一个节点为当前的6
                    p_tcb2->NextPtr             = p_tcb;
                    //当前6节点的上一个节点为 5 
                    p_tcb->PrevPtr              = p_tcb2;
                    //当前的下一个节点为8
                    p_tcb->NextPtr              = p_tcb1;
                    //8的上一个节点为6
                    p_tcb1->PrevPtr             = p_tcb; 
               } 
               //退出
               p_tcb1   = (OS_TCB*)0;
            }
            else{
                //当前插入的优先级是最大的,最后一个节点    
                if(p_tcb1->NextPtr == (OS_TCB*)0){
                    p_tcb->NextPtr              = (OS_TCB*)0;
                    p_tcb->PrevPtr              = p_tcb1;
                    p_tcb1->NextPtr             = p_tcb;
                    //退出
                    p_tcb1   = (OS_TCB*)0;
                }else{
                    p_tcb1  =  p_tcb1->NextPtr; 
                }
            }        
        }
        OSRdyList.RdyCount++;
    }

}

//移除一个任务控制块
void OS_RdyListRemove(OS_TCB *p_tcb)
{
     OS_TCB     *p_tcb1;
     OS_TCB     *p_tcb2;
     //保存要删除的tcb节点的前后
     //要删除的前一个
     p_tcb1             = p_tcb->PrevPtr;
     //要删除的后一个
     p_tcb2             = p_tcb->NextPtr;
     //如果删除的是第一个,头部
     if(p_tcb1 == (OS_TCB*)0){
         //只有一个元素
         if(p_tcb2 == (OS_TCB*)0){
            OSRdyList.RdyCount      = 0;
            OSRdyList.RdylistHead   = (OS_TCB*)0;
        }else{
          //不是只有一个节点,第二个节点变成第一个
          OSRdyList.RdyCount--;
          //删除头部之后,下一项变成头部
          p_tcb2->PrevPtr           = (OS_TCB*)0;
          //就绪表的头部指向第二个任务控制块
          OSRdyList.RdylistHead     = p_tcb2;   
        }
     }else{ 
          //不是第一个
          OSRdyList.RdyCount--;
          //删除的是最后一个?
          if(p_tcb2 == (OS_TCB*)0){
            //删除的前一个的下一个为空
            p_tcb1->NextPtr     =   (OS_TCB*)0;
          }else{
            //删除任务控制块的上一个直接指向下一个
            p_tcb1->NextPtr           = p_tcb2;
            p_tcb2->PrevPtr           = p_tcb1;
          }
     }

    //移除优先级的位置
     OS_PrioRemove(p_tcb->taskprio);

     p_tcb->PrevPtr                 = (OS_TCB*)0;
     p_tcb->NextPtr                 = (OS_TCB*)0;
}








